package com.ztgf.file.api.client;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.ztgf.common.constant.Result;
import com.ztgf.common.enums.CodeEnum;
import com.ztgf.common.utils.FileCheck;
import com.ztgf.common.utils.FileTypeDictUtils;
import com.ztgf.common.utils.FileUtils;
import com.ztgf.common.utils.StrUtils;
import com.ztgf.file.models.bo.FileBO;
import com.ztgf.file.models.bo.FileInfoSaveBO;
import com.ztgf.file.models.dto.FileInfoDTO;
import com.ztgf.file.models.dto.FileUserDTO;
import com.ztgf.file.models.dto.FileWatermarkDTO;
import com.ztgf.file.models.service.IFileInfoService;
import com.ztgf.file.models.service.IFileService;
import com.ztgf.file.models.service.IFileUserService;
import com.ztgf.file.models.service.IFileWatermarkService;
import com.ztgf.file.models.vo.FileInfoVO;
import com.ztgf.file.models.vo.FileUserVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 文件信息表控制器
 *
 * @author mxli
 * @Date 2020-07-10 14:19:43
 */

@RestController
@RequestMapping("/api/fileInfo")
@Slf4j
@Api(value = "FileInfoApiController", tags = "文件信息表Api接口")
public class FileInfoApiController {

    @DubboReference
    private IFileInfoService fileInfoService;

    @DubboReference
    private IFileService fileService;

    @DubboReference
    private IFileUserService fileUserService;

    @DubboReference
    private IFileWatermarkService fileWatermarkService;

    @Value("${file.upload-ext-name}")
    private String fileUploadExtName;

    @PostMapping("/test")
    @ApiOperation(value = "test", notes = "test")
    public Result test(Long userId, int accountType) {
        return fileInfoService.queryTest(userId, accountType);
    }

    @PostMapping("/uploadImage/{platId}")
    @ApiOperation(value = "上传图片", notes = "上传图片")
    @ApiImplicitParam(name = "platId", value = "platId", required = true, paramType = "path", dataType = "Long")
    public Result<FileInfoVO> uploadImage(@PathVariable Long platId, FileInfoSaveBO saveBO, @RequestParam("file") MultipartFile file) {

        //获取用户数
        FileUserVO fileUserVO = fileUserService.getUserVO(platId);

        if (fileUserVO == null) {
            return new Result<>(CodeEnum.FAIL_FILE_400006);
        }
        if(fileUserVO.getUseFileSize().longValue() > fileUserVO.getFileSize().longValue() * 1024 * 1024){
            return new Result<>(CodeEnum.FAIL_FILE_400009);
        }
        if (file == null || file.isEmpty()) {
            return new Result<>(CodeEnum.FAIL_FILE_400000);
        }
        FileInfoVO vo = null;

        try {
            byte[] input = file.getBytes();
            String fileExtName = FileTypeDictUtils.getExtName(input);
            if (StrUtils.isEmpty(fileExtName)) {
                return new Result<>(CodeEnum.FAIL_FILE_400007);
            }

            String originalFilename = file.getOriginalFilename();
            originalFilename = FileUtils.checkCompatible(originalFilename);
            String fileName = FileUtils.getFileName(originalFilename);
            FileUtils.getFileExtName(originalFilename);


            if((fileUserVO.getUseFileSize().longValue() + file.getSize()) > fileUserVO.getFileSize().longValue() * 1024 * 1024){
                return new Result<>(CodeEnum.FAIL_FILE_400009);
            }

            FileBO fileBO = new FileBO();
            fileBO.setFileName(fileName);
            fileBO.setFileExtName(fileExtName);
            fileBO.setInputs(input);
            fileBO.setFileSize(file.getSize());
            List<FileBO> list = new ArrayList<FileBO>();
            list.add(fileBO);
            saveBO.setFileBOS(list);
            FileWatermarkDTO watermarkDTO = null;
            //获取水印信息
            if(saveBO.getIsMark() == 1){
                Wrapper<FileWatermarkDTO> wrapper = new EntityWrapper<>();
                wrapper.eq("file_user_id", saveBO.getPlatId());

                if(saveBO.getIsMyMark() == null || saveBO.getIsMyMark() == 0){
                    //TODO 系统默认
                    wrapper.eq("child_user_id", 0);
                } else {
                    if(saveBO.getShopId() != null){
                        wrapper.eq("child_user_id", saveBO.getShopId());
                    } else {
                        //TODO 系统默认
                        wrapper.eq("child_user_id", 0);
                    }
                }

                wrapper.eq("is_use", 1);
                if(saveBO.getMarkType() != null){
                    wrapper.eq("type", saveBO.getMarkType());
                } else {
                    wrapper.eq("type", 0);
                }


                watermarkDTO = fileWatermarkService.selectOne(wrapper);
                if (watermarkDTO == null){
                    return new Result<>(CodeEnum.FAIL_FILE_400008);
                }
            }
            vo = fileService.uploadImage(saveBO, watermarkDTO);
            if(vo != null){
                if(saveBO.getIsMark() != null && saveBO.getIsMark() == 1){
                    String filePath = vo.getFileUrl();
                    String wmFileName = FileUtils.getFileName(filePath);
                    String wmFileExtName = FileUtils.getFileExtName(filePath);
                    vo.setFileUrl(wmFileName+"wm."+wmFileExtName);
                }
            }

            try{
                Thread.sleep(500);
            } catch (Exception e){
                log.error("上传文件休眠error",e);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件保存错误", e);
            return new Result<>(CodeEnum.FAIL_FILE_400001);
        }

        return new Result<>(vo);
    }

//    @PostMapping("/batchUploadImage/{platId}")
//    @ApiOperation(value = "上传图片",notes = "上传图片")
//    @ApiImplicitParam(name = "files",value = "文件列表",required = true,paramType = "query", dataType = "Long")
//    public Result<FileInfoDTO> batchUuploadImage(@PathVariable Long platId, FileInfoSaveBO saveBO, @RequestParam("files") MultipartFile[] files){
//        if(!isExist(platId)){
//            return new Result<>(CodeEnum.FAIL_FILE_400006 );
//        }
//
//        return new Result<>();
//    }

    @PostMapping("/uploadFile/{platId}")
    @ApiOperation(value = "上传文件",notes = "上传文件")
    @ApiImplicitParam(name = "platId",value = "platId",required = true,paramType = "path", dataType = "Long")
    public Result<FileInfoVO> uploadFile(@PathVariable Long platId, FileInfoSaveBO saveBO, @RequestParam("file") MultipartFile file){
        //获取用户数
        FileUserVO fileUserVO = fileUserService.getUserVO(platId);

        if (fileUserVO == null) {
            return new Result<>(CodeEnum.FAIL_FILE_400006);
        }
        if (file == null || file.isEmpty()) {
            return new Result<>(CodeEnum.FAIL_FILE_400000);
        }
        FileInfoVO vo = null;
        try {
            String originalFilename = file.getOriginalFilename();
            originalFilename = FileUtils.checkCompatible(originalFilename);
            String fileName = FileUtils.getFileName(originalFilename);
            String fileExtName = FileUtils.getFileExtName(originalFilename);

            if(!fileUploadExtName.toLowerCase().contains(fileExtName.toLowerCase())){
                return new Result<>(CodeEnum.FAIL_FILE_400010);
            }

            if((fileUserVO.getUseFileSize().longValue() + file.getSize()) > fileUserVO.getFileSize().longValue() * 1024 * 1024){
                return new Result<>(CodeEnum.FAIL_FILE_400009);
            }

            byte[] input = file.getBytes();
            FileBO fileBO = new FileBO();
            fileBO.setFileName(fileName);
            fileBO.setFileExtName(fileExtName);
            fileBO.setInputs(input);
            fileBO.setFileSize(file.getSize());
            List<FileBO> list = new ArrayList<FileBO>();
            list.add(fileBO);
            saveBO.setFileBOS(list);
            vo = fileService.uploadFile(saveBO);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件保存错误", e);
            return new Result<>(CodeEnum.FAIL_FILE_400001);
        }

        return new Result<>(vo);
    }

    @ApiOperation(value = "根据文件路径获取信息",notes = "根据文件路径获取信息")
    @PostMapping("/queryListByUrl/{platId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "platId",value = "平台id",required = true,paramType = "path", dataType = "Long")
            ,@ApiImplicitParam(name = "fileUrls",value = "fileUrls，以逗号【,】分隔",required = true,paramType = "query", dataType = "String")
    })
    public Result<List<FileInfoVO>> queryListByUrl(@PathVariable Long platId, String fileUrls){

        if(platId == null || StrUtils.isEmpty(fileUrls)){
            return new Result<>(CodeEnum.FAIL_100002 );
        }


        String[] urls = fileUrls.split(",");
        if(urls == null || urls.length <= 0){
            return new Result<>(CodeEnum.FAIL_100002 );
        }


        List<FileInfoVO> list = fileInfoService.queryListByUrl(platId, urls);

        return new Result<>(list);
    }

    @PostMapping("/batchUploadImage/{platId}")
    @ApiOperation(value = "批量上传图片",notes = "批量上传图片")
    @ApiImplicitParam(name = "files",value = "图片列表",required = true,paramType = "query", dataType = "Long")
    public Result batchUploadImage(@PathVariable Long platId, FileInfoSaveBO saveBO, @RequestParam("files") MultipartFile[] files){
        Set<FileInfoVO> fileNames = new HashSet<>();
        for (MultipartFile file : files){
            //获取用户数
            FileUserVO fileUserVO = fileUserService.getUserVO(platId);

            if (fileUserVO == null) {
                return new Result<>(CodeEnum.FAIL_FILE_400006);
            }
            if(fileUserVO.getUseFileSize().longValue() > fileUserVO.getFileSize().longValue() * 1024 * 1024){
                return new Result<>(CodeEnum.FAIL_FILE_400009);
            }
            if (file == null || file.isEmpty()) {
                return new Result<>(CodeEnum.FAIL_FILE_400000);
            }
            FileInfoVO vo = null;

            try {
                byte[] input = file.getBytes();
                String fileExtName = FileTypeDictUtils.getExtName(input);
                if (StrUtils.isEmpty(fileExtName)) {
                    return new Result<>(CodeEnum.FAIL_FILE_400007);
                }

                String originalFilename = file.getOriginalFilename();
                originalFilename = FileUtils.checkCompatible(originalFilename);
                String fileName = FileUtils.getFileName(originalFilename);
                FileUtils.getFileExtName(originalFilename);


                if((fileUserVO.getUseFileSize().longValue() + file.getSize()) > fileUserVO.getFileSize().longValue() * 1024 * 1024){
                    return new Result<>(CodeEnum.FAIL_FILE_400009);
                }
                FileBO fileBO = new FileBO();
                fileBO.setFileName(fileName);
                fileBO.setFileExtName(fileExtName);
                fileBO.setInputs(input);
                fileBO.setFileSize(file.getSize());
                List<FileBO> list = new ArrayList<FileBO>();
                list.add(fileBO);
                saveBO.setFileBOS(list);
                FileWatermarkDTO watermarkDTO = null;
                //获取水印信息
                if(saveBO.getIsMark() == 1){
                    Wrapper<FileWatermarkDTO> wrapper = new EntityWrapper<>();
                    wrapper.eq("file_user_id", saveBO.getPlatId());

                    if(saveBO.getIsMyMark() == null || saveBO.getIsMyMark() == 0){
                        //TODO 系统默认
                        wrapper.eq("child_user_id", 0);
                    } else {
                        if(saveBO.getShopId() != null){
                            wrapper.eq("child_user_id", saveBO.getShopId());
                        } else {
                            //TODO 系统默认
                            wrapper.eq("child_user_id", 0);
                        }
                    }

                    wrapper.eq("is_use", 1);
                    if(saveBO.getMarkType() != null){
                        wrapper.eq("type", saveBO.getMarkType());
                    } else {
                        wrapper.eq("type", 0);
                    }


                    watermarkDTO = fileWatermarkService.selectOne(wrapper);
                    if (watermarkDTO == null){
                        return new Result<>(CodeEnum.FAIL_FILE_400008);
                    }
                }
                vo = fileService.uploadImage(saveBO, watermarkDTO);
                if(vo != null){
                    if(saveBO.getIsMark() != null && saveBO.getIsMark() == 1){
                        String filePath = vo.getFileUrl();
                        String wmFileName = FileUtils.getFileName(filePath);
                        String wmFileExtName = FileUtils.getFileExtName(filePath);
                        vo.setFileUrl(wmFileName+"wm."+wmFileExtName);

                    }
                }
                fileNames.add(vo);
                try{
                    Thread.sleep(500);
                } catch (Exception e){
                    log.error("上传文件休眠error",e);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("文件保存错误", e);
                return new Result<>(CodeEnum.FAIL_FILE_400001);
            }
        }
        return new Result<>(fileNames);
    }

    @PostMapping("/batchUploadFile/{platId}")
    @ApiOperation(value = "批量上传文件",notes = "批量上传文件")
    @ApiImplicitParam(name = "files",value = "文件列表",required = true,paramType = "query", dataType = "Long")
    public Result batchUploadFile(@PathVariable Long platId, FileInfoSaveBO saveBO, @RequestParam("files") MultipartFile[] files){

        Set<FileInfoVO> fileNames = new HashSet<>();
        for (MultipartFile file : files){
            //获取用户数
            FileUserVO fileUserVO = fileUserService.getUserVO(platId);

            if (fileUserVO == null) {
                return new Result<>(CodeEnum.FAIL_FILE_400006);
            }
            if (file == null || file.isEmpty()) {
                return new Result<>(CodeEnum.FAIL_FILE_400000);
            }
            FileInfoVO vo = null;
            try {
                String originalFilename = file.getOriginalFilename();
                originalFilename = FileUtils.checkCompatible(originalFilename);
                String fileName = FileUtils.getFileName(originalFilename);
                String fileExtName = FileUtils.getFileExtName(originalFilename);

                if(!fileUploadExtName.toLowerCase().contains(fileExtName.toLowerCase())){
                    return new Result<>(CodeEnum.FAIL_FILE_400010);
                }

                if((fileUserVO.getUseFileSize().longValue() + file.getSize()) > fileUserVO.getFileSize().longValue() * 1024 * 1024){
                    return new Result<>(CodeEnum.FAIL_FILE_400009);
                }
                byte[] input = file.getBytes();
                FileBO fileBO = new FileBO();
                fileBO.setFileName(fileName);
                fileBO.setFileExtName(fileExtName);
                fileBO.setInputs(input);
                fileBO.setFileSize(file.getSize());
                List<FileBO> list = new ArrayList<FileBO>();
                list.add(fileBO);
                saveBO.setFileBOS(list);
                vo = fileService.uploadFile(saveBO);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("文件保存错误", e);
                return new Result<>(CodeEnum.FAIL_FILE_400001);
            }
            fileNames.add(vo);
        }
        return new Result<>(fileNames);
    }


    /**
     * 以附件形式下载文件
     *
     * @param filePath 文件地址
     * @param response
     */
    @ApiOperation(value = "以附件形式下载文件",notes = "以附件形式下载文件")
    @GetMapping("/downloadFile")
    public void downloadFile(String filePath, HttpServletResponse response) throws Exception{
        if(StringUtils.isEmpty(filePath)){
            throw new Exception(CodeEnum.FAIL_100002.getMsg());
        }

        String filename = filePath.substring(filePath.lastIndexOf("/")+1);
        String contentType = FileCheck.EXT_MAPS.get(FileCheck.getFilenameSuffix(filePath));
        try {
            byte[] fileByte = fileService.downloadFile(filePath);
            InputStream is = new ByteArrayInputStream(fileByte);
            OutputStream os = response.getOutputStream();

            if (response != null) {
                os = response.getOutputStream();

                // 设置响应头
                if (StringUtils.isNotBlank(contentType)) {
                    // 文件编码 处理文件名中的 '+'、' ' 特殊字符
                    String encoderName = URLEncoder.encode(filename, "UTF-8").replace("+", "%20").replace("%2B", "+");
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + encoderName + "\"");
                    response.setContentType(contentType + ";charset=UTF-8");
                    response.setHeader("Accept-Ranges", "bytes");
                }
            }

            byte[] buffer = new byte[1024 * 5];
            int len = 0;
            while ((len = is.read(buffer)) > 0) {
                os.write(buffer, 0, len);
            }
            os.flush();
            is.close();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 以附件形式下载文件
     *
     * @param fileUrl 文件地址
     * @param response
     */
    @ApiOperation(value = "以附件形式下载文件",notes = "以附件形式下载文件")
    @GetMapping("/downloadFile/{platId}")
    public void downloadFile(@PathVariable Long platId, String fileUrl, HttpServletResponse response) throws Exception{
        if(StringUtils.isEmpty(fileUrl)){
            throw new Exception(CodeEnum.FAIL_100002.getMsg());
        }
        FileUserVO fileUserVO = fileUserService.getUserVO(platId);

        if (fileUserVO == null) {
            throw new Exception(CodeEnum.FAIL_FILE_400006.getMsg());
        }
        String filename = fileUrl.substring(fileUrl.lastIndexOf("/")+1);
        String contentType = FileCheck.EXT_MAPS.get(FileCheck.getFilenameSuffix(fileUrl));
        try {
            byte[] fileByte = fileService.downloadFile(fileUrl);
            InputStream is = new ByteArrayInputStream(fileByte);
            OutputStream os = response.getOutputStream();

            if (response != null) {
                os = response.getOutputStream();

                // 设置响应头
                if (StringUtils.isNotBlank(contentType)) {
                    // 文件编码 处理文件名中的 '+'、' ' 特殊字符
                    String encoderName = URLEncoder.encode(filename, "UTF-8").replace("+", "%20").replace("%2B", "+");
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + encoderName + "\"");
                    response.setContentType(contentType + ";charset=UTF-8");
                    response.setHeader("Accept-Ranges", "bytes");
                }
            }

            byte[] buffer = new byte[1024 * 5];
            int len = 0;
            while ((len = is.read(buffer)) > 0) {
                os.write(buffer, 0, len);
            }
            os.flush();
            is.close();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
